import Dexie from 'dexie'
import lodash from 'lodash'
import { strToab, abTostr, strTobf, bfTostr } from './string.js'

/**
 * 数据库处理函数
 */
class Database {
    constructor(dbname) {
        // 维护数据库表 可能会有多个数据库 多张表
        this.dbs = {}
        this.dbname = dbname
        // 创建一个数据库
        this.cerateDB(dbname)
            .version(1)
            .stores(
                {
                    CacheData: 'key,createTime,exp,type'
                }
            );
    }

    /**
     * 创建一个数据库
     */
    cerateDB(name) {
        // 这里只是获得数据库实例，与传入的数据库是否已经存在没有关系，如果已经存在，就会返回已经存在的数据库的一个示例，如果不存在，就会新建一个数据库，并返回该数据库的一个实例
        this.dbs[name] = new Dexie(name)
        return this.dbs[name]
    }

    /**
     * 切换数据库
     * @param {*} name 
     * @returns 
     */
    db(name) {
        if (!this.dbs[name]) {
            return null
        }
        return this.dbs[name]
    }
    /**
     * 设置数据 添加或者更新数据库
     * @param {*} value 
     */
    async set(key, value) {
        let _ = this
        let db = await _.db(_.dbname).open()
        return db.CacheData.put(value, key)

    }
    /**
     * 获取数据库数据
     * @param {*} key 
     */
    async get(key) {
        let _ = this
        let db = await _.db(_.dbname).open()
        return db.CacheData
            .where('key')
            .equals(key)
            .toArray()
            ;
    }
    /**
     * 获取所有的数据
     * @returns 
     */
    async getAll(){
        let _ = this
        let db = await _.db(_.dbname).open()
        return db.CacheData
            .toArray()
            ;
    }
    /**
     * 移除
     */
    async remove(key) {
        let _ = this
        let db = await _.db(_.dbname).open()
        return db.CacheData.delete(key)
    }
}
// 走配置文件里面试图去读取数据库名字
let dbName = window.config && window.config.DBNAME || 'MRDATA'
// 初始化数据库
const DB = new Database(dbName)
/**
 * 获取数据
 * @param {*} key  字段名
 */
export async function get(key) {
    let data = await DB.get(key)
    if (data && data.length) {
        let item = data[0]
        let res = ''
        switch (item.type) {
            case 'String':
            case 'other':
                res = item.value
                break;
            case 'Array':
            case 'Object':
                res = JSON.parse(item.value)
                break;
            case 'Boolean':
                res = item.value === 'true'
                break;
            case 'Number':
                res = +item.value
                break;
            case 'Function':
                res = new Function(`return ` + item.value)()
                break
            case 'ArrayBuffer':
                res = strToab(item.value)
                break;
            // case 'Buffer':
            //     res = strTobf(item.value)
            //     break;
            case 'Null':
                res = null
                break;
            case 'Nan':
                res = Number.NaN
                break;
            case 'Underfined':
                res = undefined
            break;
            default:
                break;
        }
        return res
    }
    return null
}

/**
 * 设置缓存
 * @param {*} key 
 * @param {*} value 
 * @param {*} exp  默认是30天
 */
export async function set(key, value, exp = 30) {
    let now = new Date().getTime()
    let saveData = {
        'createTime': now, // 创建时间
        'key': key, // 唯一字段
        'exp': parseInt(now + 86400000 * exp), // 过期时间
        'type': '' // 数据类型
    }

    // 存储数组
    if (lodash.isArray(value)) {
        saveData.type = 'Array'
        saveData.value = JSON.stringify(value)
    }

    /**
     * 存储字符串
     */
    else if (lodash.isString(value)) {
        saveData.type = 'String'
        saveData.value = value
    }

    // 存储数字
    else if (lodash.isNumber(value)) {
        saveData.type = 'Number'
        saveData.value = value.toString()
    }

    // 存储对象
    else if (lodash.isPlainObject(value)) {
        saveData.type = 'Object'
        saveData.value = JSON.stringify(value)
    }

    // 存储ArrayBuffe
    else if (lodash.isArrayBuffer(value)) {
        saveData.type = 'ArrayBuffer'
        saveData.value = abTostr(value)
    }

    // 存储布尔型
    else if (lodash.isBoolean(value)) {
        saveData.type = 'Boolean'
        saveData.value = !!value ? 'true' : 'false'
    }

    // 存储函数
    else if (lodash.isFunction(value)) {
        saveData.type = 'Function'
        saveData.value = value.toString()
    }

    // /**
    //  * 存储buffer
    //  */
    // else if (lodash.isBuffer(value)) {
    //     saveData.type = 'Buffer'
    //     saveData.value = bfTostr(value)
    // }
    
    // null  存储
    else if (lodash.isNull(value)) {
        saveData.type = 'Null'
        saveData.value = ''
    }
    // 存储nan
    else if (lodash.isNaN(value)) {
        saveData.type = 'Nan'
        saveData.value = ''
    }

    // 存储underfined
    else if (lodash.isUndefined(value)) {
        saveData.type = 'Underfined'
        saveData.value = ''
    }
    // 存储其他格式
    else {
        console.warn('存储的格式无法解析，谨慎使用！')
        saveData.type = 'other'
        saveData.value = value.toString()
    }

    return DB.set(key, saveData)
}

/**
 * 删除某一项
 * @param {*} key 
 */
export function clearItem(key) {
    return DB.remove(key)
}

/**
 * 删除旧数据
 */
export async function deleteOldData(){
    let datas = await DB.getAll()
    if (datas && datas.length){
        for (let index = 0; index < datas.length; index++) {
            const item = datas[index];
            let now = new Date().getTime()
            let expTime = item.exp
            // 当前数据已经过期 需要删除
            if (now > expTime) {
                DB.remove(item.key)
            }
        }
    }
}


deleteOldData()

// 定时5分钟删除数据库过期数据
setInterval(() => {
    deleteOldData()
}, 5*60*1000);
